package tr.edu.boun.phys.springmassmodel.UI;

//import java.awt.Canvas;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;

import javax.swing.JPanel;

import tr.edu.boun.phys.springmassmodel.Mass;
import tr.edu.boun.phys.springmassmodel.Spring;
import tr.edu.boun.phys.springmassmodel.SpringMassModel;
import tr.edu.boun.phys.springmassmodel.Vector2D;

public class Display extends JPanel {
//public class Display extends Canvas {	
	
	private static final long serialVersionUID = 2779472812201841068L;
	
	private ResourceManager rm;
	private SpringMassModel model;
	private int N;
	
	private Mass focusedMass;
	
	private RenderingHints renderingHints;
	
	public Display(SpringMassModel model, ResourceManager resourceManager) {		 
		 this.model = model;
		 this.rm = resourceManager;
		 this.N = model.getNumberOfMasses();
		 
		 renderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, 
				 RenderingHints.VALUE_ANTIALIAS_ON);
		 renderingHints.put(RenderingHints.KEY_RENDERING,
				 RenderingHints.VALUE_RENDER_QUALITY);
		 
		 this.setBackground( Colors.BACKGROUND );
	}
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g); //clears canvas
	// Canvas icin
    //public void paint(Graphics g) {
		//super.paint(g);
		Graphics2D g2d = (Graphics2D)g;
		g2d.setRenderingHints(renderingHints);
		
		N = model.getNumberOfMasses();
		
		int nSprings = model.getNumberOfStrings();
		for(int i=0; i<nSprings; i++) {
			g2d.setColor( Colors.SPRING );
			//float penWidth = 15000.0f*(float)model.getSpring(i).getK();
			float penWidth = 2.0f;
			g2d.setStroke( new BasicStroke(penWidth) );
			g2d.draw( springShape(model.getSpring(i)) );
		}
		
		g2d.setStroke( new BasicStroke(1.8f) );
		for(int i=0; i<N; i++) {
			Mass m = model.getMass(i);
			g2d.setColor( Colors.MASS_FILL );
			
			if( m == focusedMass ) {
				g2d.setColor( Colors.FOCUSED_MASS );
			}
			if( m == rm.getSelectedMass() ) {
				g2d.setColor( Colors.SELECTED_MASS );
			}
			g2d.fill( massShape(m) );
		}
		
		for(int i=0; i<N; i++) {
			Mass m = model.getMass(i);
			g2d.setColor( Colors.MASS_STROKE );
			g2d.draw( massShape(m) );
		}
		
		
	}	
	
	private Ellipse2D.Double massShape(Mass m) {
		Vector2D v = m2v( m.getLocation() );
		double radius = 1.4*m2v(m.getM());
		return new Ellipse2D.Double(v.getX()-radius/2, v.getY()-radius/2, radius, radius);
	}
	
	private GeneralPath springShape(Spring s) {
		float x1 = (float)m2v(s.getMass1().getLocation()).x;
		float y1 = (float)m2v(s.getMass1().getLocation()).y;
		float x2 = (float)m2v(s.getMass2().getLocation()).x;
		float y2 = (float)m2v(s.getMass2().getLocation()).y;
		
		//float l = 100000*(float)s.getK();
		float l = 4;
		int N=7;
		float dx = (x2-x1)/N;
		float dy = (y2-y1)/N;
		
		GeneralPath path = new GeneralPath();
		double angle = Math.atan2(y2-y1, x2-x1);
		
		float upx = l*(float)Math.cos(angle+Math.PI/2);
		float upy = l*(float)Math.sin(angle+Math.PI/2);
		float downx = l*(float)Math.cos(angle-Math.PI/2);
		float downy = l*(float)Math.sin(angle-Math.PI/2);
		
		/*
		 * daha okunakli yap surayi...
		 */
		path.moveTo(x1, y1);
		for(int i=1; i<N-1; i+=2) {			
			path.lineTo( x1+ i   *dx +   upx, y1+ i   *dy +   upy);
			path.lineTo( x1+(i+1)*dx + downx, y1+(i+1)*dy + downy);
		}
		path.lineTo(x2, y2);
		 
		return path;
	}
	
	/*
	 * m2v: Model to View
	 * su haliyle window'u resize edince hos olmuyor
	 * yok yok hos oluyor
	 */
	public Vector2D m2v(Vector2D v0) {
		double x =   10 * v0.getX() + this.getWidth()/2.0;
		double y = - 10 * v0.getY() + this.getHeight()/2.0;
								
		return new Vector2D(x, y);		
	}
	
	public double m2v(double mass) {
		return 10.0 * mass;
	}
	
	public Vector2D v2m(Vector2D v) {
		double x = (v.getX() -  this.getWidth()/2.0) / 10.0;
		double y = (v.getY() - this.getHeight()/2.0) / -10.0;
		
		return new Vector2D(x, y);
	}
	
	
	public ResourceManager getResourceManager() {
		return rm;
	}
	
	public void setFocusedMass(Mass mass) {
		this.focusedMass = mass;
	} 
	
	public Mass getFocusedMass() {
		return focusedMass;
	}
}
